﻿using Sunny.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace DevelopTool.Common
{
    /// <summary>
    /// IP帮助类
    /// </summary>
    public static class IpHelper
    {
        /// <summary>
        /// 获取所有网卡的局域网IPv4地址
        /// </summary>
        /// <param name="ignoreVirtualNetworkInterface">是否忽略虚拟网卡ip地址 默认为true</param>
        /// <returns></returns>
        public static List<string> GetLANIPv4AddressList(bool ignoreVirtualNetworkInterface = true)
        {
            // 初始化一个用于存储IPv4地址的列表
            var ipList = new List<string>();

            try
            {
                // 使用LINQ查询获取所有符合条件的网络接口
                var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces()
                    .Where(ni => ni.OperationalStatus == OperationalStatus.Up && // 网络接口状态为启用
                                  ni.NetworkInterfaceType != NetworkInterfaceType.Loopback && // 排除回环接口
                                  ni.NetworkInterfaceType != NetworkInterfaceType.Tunnel && // 排除隧道接口
                                  ni.NetworkInterfaceType != (NetworkInterfaceType)53);

                //是否忽略虚拟网卡ip地址
                if (ignoreVirtualNetworkInterface)
                {
                    networkInterfaces = networkInterfaces.Where(ni => !IsVirtualNetworkInterface(ni.Description));
                }

                // 遍历所有符合条件的网络接口
                foreach (var ni in networkInterfaces)
                {
                    // 获取网络接口的IP属性
                    var properties = ni.GetIPProperties();
                    // 遍历网络接口的所有单播IPv4地址
                    foreach (var ip in properties.UnicastAddresses)
                    {
                        // 如果是IPv4地址，则添加到列表中
                        if (ip.Address.AddressFamily == AddressFamily.InterNetwork)
                        {
                            ipList.Add(ip.Address.ToString());
                        }
                    }
                }
            }
            catch (Exception)
            {
            }

            // 返回包含所有IPv4地址的列表
            return ipList;
        }


        /// <summary>
        /// 辅助方法，用于判断网络接口是否是虚拟的
        /// </summary>
        /// <param name="description"></param>
        /// <returns>如果是虚拟网卡，则返回true</returns>
        private static bool IsVirtualNetworkInterface(string description)
        {
            // 根据描述判断网络接口是否是虚拟的
            return description.ToUpper().Contains("VIRTUAL") ||
                   description.ToUpper().Contains("TAP-") ||
                   description.Contains("虚拟");
        }


        /// <summary>
        /// 获取当前设备公网（广域网）IPv4地址
        /// 默认5秒超时 
        /// </summary>
        /// <returns></returns>
        public static string GetWANIPv4Address(int timeout = 5000)
        {
            //随机请求获取公网ip的服务，解决偶尔请求慢的问题
            List<string> serverList = new List<string>() {
                "https://myip.ipip.net/s",
                "https://4.ipw.cn",
                "https://api-ipv4.ip.sb/ip",
                "https://icanhazip.com",
                "https://ifconfig.me/ip",
                "https://wgetip.com",
                "https://4.ident.me"
                };

            List<Task<string>> tasks = new List<Task<string>>();

            foreach (string server in serverList.RandomizeEx())//乱序排列集合
            {
                Task<string> task = Task.Factory.StartNew<string>(() =>
                {
                    try
                    {
                        //发送请求
                        HttpHelper httpHelper = new HttpHelper();
                        HttpItem item = new HttpItem()
                        {
                            URL = server,
                            Method = "GET",
                            Timeout = timeout,
                        };
                        HttpResult result = httpHelper.GetData(item);

                        if (result.StatusCode == HttpStatusCode.OK)
                            return result.Data.Replace("\n", "").Replace("\r", "").Trim();
                        else
                            return string.Empty;
                    }
                    catch
                    {
                        return string.Empty;
                    }
                });

                tasks.Add(task);
            }

            //等待第一个接口请求完成
            int doneIndex = Task.WaitAny(tasks.ToArray());
            Task<string> firstCompletedTask = tasks[doneIndex];

            //如果第一个接口成功响应，那么就返回值
            if (firstCompletedTask.IsCompleted && !firstCompletedTask.IsFaulted && firstCompletedTask.Exception == null && !string.IsNullOrWhiteSpace(firstCompletedTask.Result) && firstCompletedTask.Result.IsIPv4())
            {
                return firstCompletedTask.Result;
            }
            else//若第一个接口是响应失败的，那么就等待所有的请求接口响应完成。所以，上面的请求超时时间不能设置的太长，需要酌情设置。
            {
                tasks.RemoveAt(doneIndex);//从集合中删除第一个任务，因为在上面已经检查过任务状态了

                Task.WaitAll(tasks.ToArray());//等待所有的请求接口响应完成

                //取得成功响应的某个任务（取到的任务结果是随机的）
                Task<string> completedTask = tasks.FirstOrDefault(it => it != null && it.IsCompleted && !it.IsFaulted && it.Exception == null && !string.IsNullOrWhiteSpace(it.Result) && it.Result.IsIPv4());

                return completedTask == null ? string.Empty : completedTask.Result;
            }

        }


        /// <summary>
        /// 获取当前设备的所有可广播地址。
        /// 遍历所有网络接口，计算每个接口的广播地址并返回一个列表。
        /// </summary>
        /// <returns>包含所有广播地址的列表，如果无法获取广播地址则返回空列表。</returns>
        public static List<IPAddress> GetBroadcastAddresses()
        {
            List<IPAddress> broadcastAddresses = new List<IPAddress>();

            try
            {
                // 遍历所有网络接口
                foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces())
                {
                    // 仅处理状态为 "Up" 的接口
                    if (netInterface.OperationalStatus == OperationalStatus.Up)
                    {
                        // 获取接口的 IP 地址信息
                        foreach (UnicastIPAddressInformation ip in netInterface.GetIPProperties().UnicastAddresses)
                        {
                            // if (ip.Address.ToString() == "127.0.0.1") continue;

                            // 仅处理 IPv4 地址
                            if (ip.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                            {
                                byte[] ipAdressBytes = ip.Address.GetAddressBytes();
                                byte[] subnetMaskBytes = ip.IPv4Mask.GetAddressBytes();

                                // 确保 IP 地址和子网掩码的长度相同
                                if (ipAdressBytes.Length != subnetMaskBytes.Length) continue;

                                // 计算广播地址
                                byte[] broadcastAddress = new byte[ipAdressBytes.Length];
                                for (int i = 0; i < broadcastAddress.Length; i++)
                                {
                                    // 广播地址 = IP 地址 | (子网掩码 ^ 255)
                                    broadcastAddress[i] = (byte)(ipAdressBytes[i] | (subnetMaskBytes[i] ^ 255));
                                }

                                // 添加到广播地址列表中
                                broadcastAddresses.Add(new IPAddress(broadcastAddress));
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
            }
            return broadcastAddresses;
        }

    }
}
